MDI窗体不闪烁方法测试通过:
1 | //.net 4.0用OptimizedDoubleBuffer |
真正有效的方法:在最上层窗体加上
1 | protected override CreateParams CreateParams { |
在下层的窗体和自定义控件加上
1 | protected override CreateParams CreateParams |
注意:如果加错地方或人品不好,某些时候可能会造成控件绘制略微不正常。
如果人品爆发的话,貌似在下层窗体直接加 cp.Style &= ~0x02000000 就行,不需要在上层窗体加 cp.ExStyle |= 0x02000000;
注意下层窗体代码在ListBox或者ListView的Anchor设有Right,且窗体BackColor与控件背景不同的时候,可能会发现控件初始化显示不正常。需要做一下MdiParent.Refresh或者取消Right;
引用MSDN中对CreateParams的说明:
在你开发的重载控件中不要重写这个属性,通过这个属性控制控件的某些风格。只有在你封装Windows控件或者想实现某些WinForm没有提供的风格(比如Layered Window)控制的时候再使用这个属性。更多信息请参照MSDN上对CreateWindow方法和CreateWindowEx方法的参数CREATESTRUCT结构体的文档注释。
简述为何CreateParams能够实现这样高级的样式控制,因为从CreateWindow和CreateWindowEx的名字就可以看出,CreateParam是传递给这俩个方法的参数,而这两个方法又是在窗体创建的时候调用的。所以,CreateParam才能够实现如此强大的样式控制。
节点更新要使用 BeginUpdate 和 EndUpdate
这一对操作对于需要批量操作更新控件的情景有比较好的效果,比如初始化时批量添加了大量节点。坏处就在于不能即时更新。所以,对于频繁的更新节点并希望立即反映到界面的情况不适用。如果使用并且没有禁掉清除界面消息的话,则控件看起来就会不停的闪烁,而且以白底为主,内容几乎不可见(这个视频繁程度而定)。因为界面更新都在EndUpdate处完成,操作太多导致EndUpdate阻塞时间过长,且清空在先,更新在后,导致界面看起来长时间处于空白状态。
某些情况下可以使用禁止背景更新
1 | protected override void WndProc( ref Message m ) |
使用Windows API中的SendMessage函数:
1 | /* 拦截控件重绘 */ |
SendMessage函数中,发送消息 WM_SETREDRAW,设置SETREDRAW为FALSE,导致窗口不进行绘制。
此时,看到的窗体是假的,现象:鼠标形状是后面应用程序的形状;鼠标划过,后面的应用程序就显示出来了。人眼看到的就是“花屏”。